using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options;
using System.Security.Claims;
using System.Text.Encodings.Web;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.Tokens;
using Microsoft.IdentityModel.JsonWebTokens;
using System.Text;

namespace MyBlogServer.Services
{
    public class CustomSessionOptions : AuthenticationSchemeOptions
    {
        public string SecretKey { get; set; } = string.Empty;
    }

    public class CustomSessionHandler : AuthenticationHandler<CustomSessionOptions>
    {
        private readonly string _secretKey;
        
        public CustomSessionHandler(
            IOptionsMonitor<CustomSessionOptions> options,
            ILoggerFactory logger,
            UrlEncoder encoder,
            IConfiguration configuration)
            : base(options, logger, encoder)
        {
            _secretKey = configuration["Jwt:SecretKey"] ?? throw new ArgumentNullException(nameof(configuration));
        }

        protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            try
            {
                // 从Authorization头部获取JWT Token
                var authorizationHeader = Context.Request.Headers["Authorization"].FirstOrDefault();
                if (string.IsNullOrEmpty(authorizationHeader) || !authorizationHeader.StartsWith("Bearer "))
                {
                    return AuthenticateResult.NoResult();
                }

                var token = authorizationHeader.Substring("Bearer ".Length).Trim();
                if (string.IsNullOrEmpty(token))
                {
                    return AuthenticateResult.NoResult();
                }

                // 验证JWT Token
                var tokenHandler = new JsonWebTokenHandler();
                var key = Encoding.ASCII.GetBytes(_secretKey);
                
                var validationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = true,
                    ValidIssuer = Context.RequestServices.GetRequiredService<IConfiguration>()["Jwt:Issuer"],
                    ValidateAudience = true,
                    ValidAudience = Context.RequestServices.GetRequiredService<IConfiguration>()["Jwt:Audience"],
                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.Zero
                };

                var validationResult = await tokenHandler.ValidateTokenAsync(token, validationParameters);
                if (!validationResult.IsValid)
                {
                    Logger.LogWarning("JWT Token验证失败: {Error}", validationResult.Exception?.Message);
                    return AuthenticateResult.Fail("Token验证失败");
                }

                var jsonWebToken = (JsonWebToken)validationResult.SecurityToken;
                var username = jsonWebToken.Subject;
                
                if (string.IsNullOrEmpty(username))
                {
                    return AuthenticateResult.NoResult();
                }

                // 创建ClaimsIdentity
                var claims = new[] {
                    new Claim(ClaimTypes.Name, username),
                    new Claim(ClaimTypes.NameIdentifier, username)
                };

                var identity = new ClaimsIdentity(claims, Scheme.Name);
                var principal = new ClaimsPrincipal(identity);
                var ticket = new AuthenticationTicket(principal, Scheme.Name);

                return AuthenticateResult.Success(ticket);
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "认证处理过程中发生错误");
                return AuthenticateResult.Fail(ex);
            }
        }
        
        protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
        {
            try
            {
                // 重定向到登录页面
                Response.Redirect("/admin/login");
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "处理认证挑战时发生错误");
                // 如果重定向失败，返回401
                Response.StatusCode = 401;
            }
        }
        
        protected override async Task HandleForbiddenAsync(AuthenticationProperties properties)
        {
            try
            {
                // 对于禁止访问的情况，也重定向到登录页面
                Response.Redirect("/admin/login");
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "处理禁止访问时发生错误");
                // 如果重定向失败，返回403
                Response.StatusCode = 403;
            }
        }
    }
}